package com.lyc.platform.message.core.message;

import cn.hutool.core.util.TypeUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.util.TypeUtils;
import com.lyc.platform.message.core.header.HeaderKey;
import com.lyc.platform.message.core.json.Jsonable;
import com.sun.istack.internal.Nullable;

import java.io.Serializable;
import java.util.Map;
import java.util.Optional;

/**
 * 根消息的定义
 *
 * @author liangyucheng
 */
public interface Message extends Jsonable, Serializable {

    default MessageType getMessageType() {
        return null;
    }

    /**
     * 消息的唯一id，全系统唯一
     * 需要做一个全局id
     * 有些设备不支持消息ID，可以在协议包中进行消息绑定
     *
     * @return 消息id
     */
    String getMessageId();

    /**
     * 返回当时消息的时间戳
     *
     * @return timestamp
     */
    long getTimestamp();

    /**
     * 消息头
     *
     * @return headers or null
     */
    @Nullable
    Map<String, Object> getHeaders();

    /**
     * 给信息添加header
     *
     * @param header 消息头
     * @param value  消息值
     * @return 当前消息
     */
    Message addHeader(String header, Object value);

    /**
     * 给消息添加消息头，如果存在消息头则添加失败
     *
     * @param header
     * @param value
     * @return
     */
    Message addHeaderIfAbsent(String header, Object value);

    default <T> Message addHeader(HeaderKey<T> header, T value) {
        return addHeader(header.getKey(), value);
    }

    @SuppressWarnings("all")
    default <T> Optional<T> getHeader(HeaderKey<T> key) {
        return getHeader(key.getKey())
                .map(v -> TypeUtils.cast(v, key.getType(), ParserConfig.global));
    }

    default <T> T getHeaderOrDefault(HeaderKey<T> key) {
        return getHeader(key).orElseGet(key::getDefaultValue);
    }

    /**
     * @see Message#addHeaderIfAbsent(String, Object)
     */
    default <T> Message addHeaderIfAbsent(HeaderKey<T> header, T value) {
        return addHeaderIfAbsent(header.getKey(), value);
    }

    /**
     * 删除消息中的消息头
     *
     * @param header 消息头
     * @return 此消息
     */
    Message removeHeader(String header);

    /**
     * 获取消息中所有的消息头，如果存在的话
     * 有效避免空指针异常
     *
     * @param header 消息头
     * @return Optional 类
     */
    default Optional<Object> getHeader(String header) {
        return Optional.ofNullable(getHeaders())
                .map(headers -> headers.get(header));
    }
}